#include "configmanager.h"
#include <iostream>
#include <fstream>
#include "Utility.h"
#include "errordialogmanager.h"
#include "logger.h"
#include "parametermodel.h"
#include "popupmanager.h"
#include "qurl.h"
#include "source/tools.h"
#include <QVariantMap>
#include <fstream>
#include <QString>
#include <QFile>
#include <QTextStream>
#include <QDir>
#include <QUrl>
#include <QFileInfo>

Q_DECLARE_METATYPE(QVector<int>)

ConfigManager::ConfigManager(QObject *parent): QObject(parent)
{
    QString result = ConfigPath+"parameters_schema.yaml";
    loadConfigTable(result.toStdString());

    ensureDirectoryExists(ConfigPath + "usr/");


    checkAndCreateFile(ConfigPath + "usr/"+defaultPath);
    QString lastValueFile = getLastValueTablePath();

    if(lastValueFile.isEmpty() || lastValueFile == defaultPath)
    {
        qDebug()  << "lastValueFile is default Now creatNew it";
        initializeValuesFromConfig();
        setLastValueTablePath(defaultPath);
        LogInfo << "ValueTable_ content: \n" << valueTable_;
        emit valueTableLoad();
        emit valueTableChanged();
    }else{
        result = ConfigPath + "usr/" + getLastValueTablePath();
        qDebug()  << "select ValueTabel file :" << result;
        //result = ConfigPath+"default.yaml";
        loadOrCreateValueTable(result.toStdString());
    }


}

ConfigManager::~ConfigManager() {}

ConfigManager& ConfigManager::getInstance() {
    static ConfigManager instance;
    return instance;
}

void ConfigManager::setLastValueTablePath(const QString& path) {
    QString filePath= ConfigPath + "lastPath.txt";
    QFile file(filePath);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QTextStream out(&file);
        out << path;
        file.close();
    } else {
        LogError << "Unable to open file for writing: " << filePath.toStdString() << std::endl;
    }
}

QString ConfigManager::getLastValueTablePath()
{

    QString filePath= ConfigPath + "lastPath.txt";
    QFile file(filePath);
    if (!file.exists()) {
        qWarning() << "[" << file << "] not exists";
        // 如果文件不存在，则创建文件并写入默认路径
        setLastValueTablePath(defaultPath);
        return defaultPath;
    }

    if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QTextStream in(&file);
        QString path = in.readLine().trimmed();
        file.close();

        // 检查读取的路径是否为空或者是否以.yaml结尾
        if (path.isEmpty() || !path.endsWith(".yaml")) {
            path = defaultPath;
            setLastValueTablePath(defaultPath);
        }
        return path;
    }else {
        LogError << "Unable to open file for reading: " << ConfigPath+"LastPath.txt" ;
    }

    return QString();
}



void ConfigManager::loadConfigTable(const std::string& configTableFile) {
    std::lock_guard<std::mutex> lock(mutex_);
    LogDebug << "Loading loadConfigTable ....:" << configTableFile;
    configTable_ = YAML::LoadFile(configTableFile);
    LogInfo << "Success load file" << configTableFile;
}

QVariant ConfigManager::parseValue(const YAML::Node &node) const {
    switch (node.Type()) {
    case YAML::NodeType::Null:
        return QVariant();
    case YAML::NodeType::Scalar:
        try {
            // 尝试解析为布尔值
            QString scalarValue = QString::fromStdString(node.Scalar()).trimmed();
            if (scalarValue == "true") {
                return QVariant(true);
            } else if (scalarValue == "false") {
                return QVariant(false);
            }

            // 尝试解析为整数
            bool ok;
            int intValue = scalarValue.toInt(&ok);
            if (ok) {
                return QVariant(intValue);
            }

            // 尝试解析为浮点数
            float floatValue = scalarValue.toFloat(&ok);
            if (ok) {
                return QVariant(floatValue);
            }

            // 默认解析为字符串
            return QVariant(scalarValue);
        } catch (...) {
            return QVariant(QString::fromStdString(node.Scalar()));
        }
    case YAML::NodeType::Sequence: {
        QVariantList list;
        for (const auto &elem : node) {
            list.append(parseValue(elem)); // 递归处理，支持嵌套列表
        }
        return list;
    }
    case YAML::NodeType::Map: {
        QVariantMap map;
        for (const auto &elem : node) {
            map[QString::fromStdString(elem.first.as<std::string>())] = parseValue(elem.second);
        }
        return map;
    }
    default:
        qCritical() << "Unknown node type";
        return QVariant();
    }
}

void ConfigManager::loadOrCreateValueTable(const std::string& valueTableFile) {
    {
        std::lock_guard<std::mutex> lock(mutex_);

        QString qFilePath = QString::fromStdString(valueTableFile);
        LogDebug << "loadOrCreateValueTable1 :" << qFilePath;
        // QUrl qurl(qFilePath);

        // 检查是否是URL格式


        if (qFilePath.startsWith("files://")) {
            qFilePath = qFilePath.mid(8);
        }
        QString filePath = qFilePath;
        // if (qurl.isLocalFile()) {
        //     filePath = qurl.toLocalFile();
        // } else {
        //     filePath = qFilePath;
        // }
        LogDebug << "loadOrCreateValueTable :" << filePath;
        QFile file(filePath);
        if (file.exists() && !qFilePath.contains(defaultPath)) {

            std::string stdFilePath = filePath.toStdString();

            // 使用 QFileInfo 获取文件信息
            QFileInfo fileInfo(filePath);
            setLastValueTablePath(fileInfo.fileName());
            configfileName_ = fileInfo.completeBaseName();

            emit fileNameChanged();
            valueTable_.clear();

            // 读取文件内容
            YAML::Node tempValueTable = YAML::LoadFile(stdFilePath);
            // 处理临时值表
            for (const auto& section : configTable_) {
                const std::string& sectionName = section.first.as<std::string>();
                for (const auto& param : section.second) {
                    const std::string& paramName = param.first.as<std::string>();
                    QString key = QString::fromStdString(sectionName + "/" + paramName);
                    if (tempValueTable[sectionName][paramName]) {
                        YAML::Node paramValue = tempValueTable[sectionName][paramName];
                        // if (validateValue(configYaml_[sectionName][paramName], paramValue)) {
                        valueTable_[key] = parseValue(paramValue);

                    } else {
                        qWarning() <<  "Invalid paramConfig used in default: " <<
                            QString::fromStdString(sectionName) << " and " << QString::fromStdString(paramName);
                        valueTable_[key] = parseValue(configTable_[sectionName][paramName]["default"]);
                    }
                }
                // 如果值表中有该段落，处理其中的参数
                // if (tempValueTable[sectionName]) {
                //     for (const auto& param : section.second) {
                //         const std::string& paramName = param.first.as<std::string>();
                //         if (tempValueTable[sectionName][paramName]) {
                //             YAML::Node paramValue = tempValueTable[sectionName][paramName];
                //             YAML::Node paramConfig = configTable_[sectionName][paramName];
                //             if (validateValue(paramConfig, paramValue)) {
                //                 QVariantMap sectionMap = valueTable_.value(QString::fromStdString(sectionName)).toMap();
                //                 sectionMap[QString::fromStdString(paramName)] = parseValue(paramValue);
                //                 valueTable_[QString::fromStdString(sectionName)] = sectionMap;
                //                 LogDebug << "Invalid paramConfig used in: " << QString::fromStdString(sectionName) << " and " << QString::fromStdString(paramName)
                //                          <<" value :" << parseValue(paramValue).toString();
                //             } else {
                //                 LogWarning << "Invalid paramConfig used in default: " << QString::fromStdString(sectionName) << " and " << QString::fromStdString(paramName);
                //                 QVariantMap sectionMap = valueTable_.value(QString::fromStdString(sectionName)).toMap();
                //                 sectionMap[QString::fromStdString(paramName)] = parseValue(paramConfig["default"]);
                //                 valueTable_[QString::fromStdString(sectionName)] = sectionMap;
                //             }valueTableLoad
                //         } else {
                //             // 如果值表中没有这个参数，使用配置表的默认值
                //             QVariantMap sectionMap = valueTable_.value(QString::fromStdString(sectionName)).toMap();
                //             sectionMap[QString::fromStdString(paramName)] = parseValue(configTable_[sectionName][paramName]["default"]);
                //             valueTable_[QString::fromStdString(sectionName)] = sectionMap;
                //         }
                //     }
                // } else {
                //     // 如果值表中没有这个段落，使用配置表中的所有默认值
                //     for (const auto& param : section.second) {
                //         const std::string& paramName = param.first.as<std::string>();
                //         QVariantMap sectionMap = valueTable_.value(QString::fromStdString(sectionName)).toMap();
                //         sectionMap[QString::fromStdString(paramName)] = parseValue(configTable_[sectionName][paramName]["default"]);
                //         valueTable_[QString::fromStdString(sectionName)] = sectionMap;
                //     }
                // }
            }
        } else {
            LogError << valueTableFile << " not found. Creating it...:" << valueTableFile;
            initializeValuesFromConfig();
        }
    }
    LogInfo << "ValueTable_ content: \n" << valueTable_;
    LogInfo << "Atempting to valueTableLoad " ;
    emit valueTableLoad();
    emit valueTableChanged();
    LogInfo << " valueTableLoad  finish" ;
    //ParameterModel::getInstance().applyParameters(valueTable_);

}

void ConfigManager::initializeValuesFromConfig() {
    for (const auto& section : configTable_) {
        const std::string& sectionName = section.first.as<std::string>();
        for (const auto& param : section.second) {
            const std::string& paramName = param.first.as<std::string>();
            QString key = QString::fromStdString(sectionName + "/" + paramName);
            valueTable_[key] = parseValue(configTable_[sectionName][paramName]["default"]);
        }
    }
    configfileName_ = "default";
    emit fileNameChanged();
}
YAML::Node ConfigManager::convertToYamlNode(const QVariant& value) {
    YAML::Node node;

    switch (value.type()) {
    case QVariant::Map: {
        QVariantMap map = value.toMap();
        for (auto it = map.begin(); it != map.end(); ++it) {
            node[it.key().toStdString()] = convertToYamlNode(it.value());
        }
        break;
    }
    case QVariant::List: {
        QVariantList list = value.toList();
        for (const QVariant& item : list) {
            if (item.canConvert<QVariantList>()) {
                node.push_back(convertToYamlNode(item.toList()));
            } else if (item.canConvert<QVector<int>>()) {
                QVector<int> vector = item.value<QVector<int>>();
                YAML::Node vectorNode;
                for (int val : vector) {
                    vectorNode.push_back(val);
                }
                node.push_back(vectorNode);
            } else {
                node.push_back(convertToYamlNode(item));
            }
        }
        break;
    }
    case QVariant::Bool:
        node = value.toBool();
        break;
    case QVariant::Int:
        node = value.toInt();
        break;
    case QVariant::Double:
        node = value.toDouble();
        break;
    case QVariant::String:
        node = value.toString().toStdString();
        break;
    default:
        qWarning() << "Unhandled QVariant type:" << value.typeName() ;
        node = value.toString().toStdString();
        break;
    }

    return node;
}

bool ConfigManager::saveValueTable(const std::string& valueTableFile) {
    std::lock_guard<std::mutex> lock(mutex_);

    QString filePath(QString::fromStdString(valueTableFile));
    LogInfo << "Attempting to saveValueTable :" << filePath;
    // 将 URL 转换为本地文件路径
    QUrl url(filePath);
    QString localFilePath = url.toLocalFile();
    QFileInfo fileInfo(localFilePath);
    QString baseName = fileInfo.baseName();
    LogDebug << "saveValueTable get baseName: " << baseName;
    // 转换 QVariantMap 到 YAML::Node

    YAML::Node rootNode;
    for (auto it = valueTable_.begin(); it != valueTable_.end(); ++it) {
        QString key = it.key();
        QStringList parts = key.split('/');
        if (parts.size() == 2) {
            std::string section = parts[0].toStdString();
            std::string param = parts[1].toStdString();
            rootNode[section][param] = convertToYamlNode(it.value());
        }
    }

    // 使用 yaml-cpp 将 YAML::Node 写入文件

    YAML::Emitter out;
    out << rootNode;

    std::ofstream outFile(localFilePath.toStdString());
    if (!outFile) {
        LogError << "Config Manager failed to open file for writing:" << localFilePath.toStdString();
        ErrorDialogManager::instance().showNonBlockingInfo("保存配置失败","无法打开等待写入文件");
        return false;
    }

    outFile << out.c_str();
    if (!outFile) {
        LogError << "Config Manager failed to write to file:" << localFilePath.toStdString();
        ErrorDialogManager::instance().showNonBlockingInfo("保存配置失败","无法写入文件");
        return false;
    }

    LogInfo << "Config Manager saveValueTable successful:" << localFilePath.toStdString();
    ErrorDialogManager::instance().showNonBlockingInfo("保存配置失败","保存成功");
    configfileName_ = baseName;
    setLastValueTablePath(fileInfo.fileName());
    emit fileNameChanged();
    return true;

}


QVariantMap ConfigManager::getAllParametersByCategory(std::string category) const {
    std::lock_guard<std::mutex> lock(mutex_);
    QVariantMap section;

    if (configTable_[category]) {
        YAML::Node sectionNode = configTable_[category];
        for (YAML::const_iterator paramIt = sectionNode.begin(); paramIt != sectionNode.end(); ++paramIt)
        {
            QVariantMap Params;
            QString sectionKey = QString::fromStdString(paramIt->first.as<std::string>());

            Params["value"] = valueTable_[QString::fromStdString(category)].toMap()[sectionKey];
            // if(YAML::Node valueIt = valueTable_[category][sectionKey.toStdString()])
            // {
            //     Params["value"] = yamlNodeQVariant(valueIt);
            // }else{
            //     LogWarning << "failed getAllParametersByCategory not find in category valueTable_: " << sectionKey.toStdString();
            // }
            for (YAML::const_iterator configIt = paramIt->second.begin(); configIt != paramIt->second.end(); ++configIt)
            {
                QString configKey = QString::fromStdString(configIt->first.as<std::string>());
                Params[configKey] = yamliteratorQVariant(configIt);
            }
            section[sectionKey] = Params;
        }
    }else{
        LogWarning << "failed getAllParametersByCategory not find: " << category;
    }

    return section;
}


QVariantMap ConfigManager::getConfig(const std::string &section, const std::string &parameterName)
{
    if (configTable_[section])
    {
        QVariant config_;
        if (YAML::convert<QVariant>::decode(configTable_[section][parameterName], config_))
        {
            return config_.toMap();
        }
    }
    return QVariantMap();
}

bool ConfigManager::checkAndCreateFile(const QString &filePath)
{
    QFile file(filePath);

    // 检查文件是否存在
    if (!file.exists()) {
        LogDebug << "creat new Default.yaml";
        // 如果文件不存在，尝试创建文件
        if (file.open(QIODevice::WriteOnly)) {
            // 可以向文件中写入一些默认内容
            QTextStream out(&file);
            out << "# Default YAML content" << Qt::endl; // 默认内容
            file.close();
            return true; // 成功创建文件
        } else {
            return false; // 文件创建失败
        }
    }
    return true; // 文件已存在
}


void ConfigManager::configParamSave()
{
    LogDebug << "Atempting to configParamSave";
    try {
        saveValueTable("master/config/parameter_values.yaml");
    } catch (const std::exception& ex) {
        LogError <<"Fail saveValueTable"<< ex.what() << std::endl;
    }
    LogInfo << "configParamSave successfull";
}


QVariantMap ConfigManager::getAllParameters() const {
    // std::lock_guard<std::mutex> lock(mutex_);
    // QVariantMap parameters;

    // for (YAML::const_iterator sectionIt = valueTable_.begin(); sectionIt != valueTable_.end(); ++sectionIt) {
    //     QString section = QString::fromStdString(sectionIt->first.as<std::string>());
    //     parameters[section] = getAllParametersByCategory(section.toStdString());
    // }
    // return parameters;
    return valueTable_;
}


// QVariant ConfigManager::getParameter(const std::string &section, const std::string &key) const {
//     QVariantMap sectionMap = valueTable_.value(QString::fromStdString(section)).toMap();
//     if (sectionMap.contains(QString::fromStdString(key))) {
//         return sectionMap.value(QString::fromStdString(key));
//     } else {
//         qCritical() << "Parameter not found [" << QString::fromStdString(section) << "] [" << QString::fromStdString(key) << "]";
//         throw std::runtime_error("Parameter not found");
//     }
// }


bool ConfigManager::validateValue(const YAML::Node& paramConfig, const YAML::Node& value) {
    //屏蔽到类型验证
    return true;
    if (!paramConfig["type"]) return false;
    const YAML::Node& typeNode = paramConfig["type"];

    if (!validateType(typeNode, value)) return false;

    // 对于标量类型，验证范围（最小值/最大值）
    std::string type = typeNode.IsScalar() ? typeNode.as<std::string>() : "";
    if (type == "int" && paramConfig["min"]) {
        int intValue = value.as<int>();
        if (paramConfig["min"] && intValue < paramConfig["min"].as<int>()) return false;
        if (paramConfig["max"] && intValue > paramConfig["max"].as<int>()) return false;
    } else if (type == "float") {
        float floatValue = value.as<float>();
        if (paramConfig["min"] && floatValue < paramConfig["min"].as<float>()) return false;
        if (paramConfig["max"] && floatValue > paramConfig["max"].as<float>()) return false;
    }

    return true;
}

bool ConfigManager::validateType(const YAML::Node& typeNode, const YAML::Node& value) {
    if (typeNode.IsScalar()) {
        std::string type = typeNode.as<std::string>();
        if (type == "int") return value.IsScalar() && value.as<int>();
        else if (type == "float") return value.IsScalar() && value.as<float>();
        else if (type == "string") return value.IsScalar();
        return false;
    }
    return true;
    if (typeNode.IsSequence()) {
        if (!value.IsSequence() || typeNode.size() != value.size()) return false;
        for (size_t i = 0; i < typeNode.size(); ++i) {
            if (!validateType(typeNode[i], value[i])) return false;
        }
        return true;
    }

    return false;
}

int testParametertable()
{
    ConfigManager& configManager = ConfigManager::getInstance();

    configManager.loadConfigTable("master/config/parameters_schema.yaml");
    configManager.loadOrCreateValueTable("master/config/parameter_values.yaml");

    try {
        configManager.saveValueTable("master/config/parameter_values.yaml");
    } catch (const std::exception& ex) {
        LogError << ex.what() << std::endl;
    }

    return 0;
}
